package cn.flexui.flexuiserver.service.impl;

import cn.flexui.flexuiserver.domain.constant.AccountConts;
import cn.flexui.flexuiserver.domain.constant.PaymentConts;
import cn.flexui.flexuiserver.domain.entity.MemberCard;
import cn.flexui.flexuiserver.domain.entity.MemberRights;
import cn.flexui.flexuiserver.domain.entity.PaymentInfo;
import cn.flexui.flexuiserver.domain.entity.UserMemberRights;
import cn.flexui.flexuiserver.mapper.PaymentInfoMapper;
import cn.flexui.flexuiserver.service.*;
import cn.flexui.flexuiserver.utils.IdGenerate;
import cn.flexui.flexuiserver.utils.MathUtils;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.stripe.model.PaymentIntent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 支付信息表 服务实现类
 * </p>
 *
 * @author apeto
 * @since 2024-10-13 03:49:49
 */
@Slf4j
@Service
public class PaymentInfoServiceImpl extends ServiceImpl<PaymentInfoMapper, PaymentInfo> implements PaymentInfoService {

    @Autowired
    private AccountService accountService;
    @Autowired
    private MemberCardService memberCardService;
    @Autowired
    private MemberRightsService memberRightsService;
    @Autowired
    private UserMemberRightsService userMemberRightsService;

    @Override
    public PaymentInfo getPaySn(String paySn) {
        LambdaQueryWrapper<PaymentInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PaymentInfo::getPaySn,paySn);
        return getOne(queryWrapper);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void handleSuccessfulPayment(PaymentIntent paymentIntent) {
        Long amount = paymentIntent.getAmount();
        String paySn = getPaySn(paymentIntent);
        PaymentInfo paymentInfo = getPaySn(paySn);
        if (MathUtils.toYuan(amount).compareTo(paymentInfo.getPayAmount()) != 0) {
            log.error("支付金额与订单金额不一致，支付金额：{}，订单金额：{}", amount, paymentInfo.getPayAmount());
            return;
        }

        paymentInfo.setPayState(PaymentConts.PayStateEnum.PAY_SUCCESS.getState());
        paymentInfo.setPayTime(new Date(paymentIntent.getCreated() * 1000));
        updateById(paymentInfo);

        // 增加账户金额
        log.info("支付成功，支付流水：{}，支付金额：{}", paySn, amount);

        Long userId = paymentInfo.getUserId();
        String goodsCode = paymentInfo.getGoodsCode();
        Long memberCardId = Long.valueOf(goodsCode);
        MemberCard memberCard = memberCardService.getById(memberCardId);
        List<MemberRights> rightsList = memberRightsService.getByMemberCode(memberCardId);
        Date startTime = new Date();
        Integer count = 0;
        for (MemberRights memberRights : rightsList) {
            UserMemberRights entity = new UserMemberRights();
            entity.setMemberCardId(memberCard.getId());
            entity.setMemberRightsId(memberRights.getId());
            entity.setUserId(userId);
            entity.setStartTime(startTime);
            entity.setEndTime(DateUtil.offsetDay(startTime, memberCard.getCardDay()));
            userMemberRightsService.save(entity);
            count += memberRights.getCount();
        }
        String outsideCode = IdGenerate.getId();
        AccountConts.LogDescriptionTypeEnum ldType = AccountConts.LogDescriptionTypeEnum.RECHARGE;
        AccountConts.DirectionTypeEnum typeEnum = AccountConts.DirectionTypeEnum.IN;
        Integer accountType = AccountConts.AccountTypeEnum.COUNT_BALANCE.getType();
        accountService.commonUpdateAccount(userId, accountType, BigDecimal.valueOf(count), paySn, outsideCode, ldType, typeEnum, userId + "");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handleFailedPayment(PaymentIntent paymentIntent) {
        String paySn = getPaySn(paymentIntent);
        PaymentInfo paymentInfo = getPaySn(paySn);
        paymentInfo.setPayState(PaymentConts.PayStateEnum.PAY_FAIL.getState());
        updateById(paymentInfo);
    }

    public String getPaySn(PaymentIntent paymentIntent) {

        Map<String, String> metadata = paymentIntent.getMetadata();
        return metadata.get("paySn");
    }
}
